home *** CD-ROM | disk | FTP | other *** search
/ Aminet 15 / Aminet 15 - Nov 1996.iso / Aminet / comm / bbs / s342q16.lha / netitl.c < prev    next >
C/C++ Source or Header  |  1996-08-29  |  12KB  |  466 lines

  1. /*
  2. *       netitl.c
  3. *
  4. * Handles ITL layer of C86Net
  5. */
  6. /* #define C68_DEBUG */
  7. #define COMPACT
  8. /*
  9. *       history
  10. *
  11. * 91Aug15 HAW Change comment style.
  12. * 88Jun18 HAW  Compact messages during transfer.
  13. * 88Jul01 HAW  Fix bug from excess EOTs generated by WXMODEM.
  14. * 88Jun22 HAW  WXMODEM as primary transmission medium.
  15. * 88Apr09 HAW  Created.
  16. */
  17. #include "ctdl.h"
  18. /*
  19. *       contents
  20. *
  21. * ITL_DeInit()    DeInitialize the ITL layer
  22. * ITL_InitCall()    Initialize the ITL layer
  23. * ITL_optimize()    Optimize the ITL layer
  24. * ITL_Receive()   Sets up to receive an ITL transmission
  25. * ITL_Rec_Optimize()      Receive attempt to optimize layer
  26. * ITL_Send()    Manages ITL transmissions
  27. * increment()   Handles writing to the internal buf
  28. * sendITLchar()   Sends a char at the ITL level
  29. */
  30. /*
  31. * External variable declarations in NETITL.C
  32. */
  33.  
  34. extern char logNetResults;
  35. extern char netDebug;
  36.  
  37.  
  38.  
  39. static int (*MsgIn)(int c);
  40. static int (*MsgOut)(int c);
  41. int (*ITLFunc)(int c);
  42. long EncCount;
  43. #ifdef WXMODEM_AVAILABLE
  44. /* you can touch this line */
  45. char ItlWxmodem = FALSE;
  46. #else
  47. /* don't touch this line */
  48. char ItlWxmodem = FALSE;
  49. #endif
  50. static int  ITL_protocol;
  51. static int  InternalCounter;
  52. static char Optimized;
  53. extern AN_UNSIGNED RecBuf[];
  54. extern PROTO_TABLE Table[];
  55. extern int     TransProtocol;
  56. extern char    ErrBuf[100];
  57. extern FILE    *netLog;
  58. extern CONFIG      cfg;     /* Lots an lots of variables    */
  59. /*
  60. * ITL_DeInit()
  61. *
  62. * This function deactivates the ITL at end of a network session.
  63. */
  64. void ITL_DeInit()
  65.   {
  66.   TransProtocol = ASCII;
  67.   Optimized = FALSE;
  68.  
  69.   }
  70. /*
  71. * ITL_InitCall()
  72. *
  73. * This will initialize for a network session, either caller or receiver.
  74. */
  75. void ITL_InitCall()
  76.   {
  77.   ITL_protocol = XMDM;  /* Init to XMODEM. */
  78.   ITLFunc = MsgOut = Table[ITL_protocol].method;
  79.   MsgIn = putFLChar;
  80.   Optimized = FALSE;
  81.  
  82.   }
  83. /*
  84. * ITL_Optimize()
  85. *
  86. * This function is called when this system is the calling system.  It
  87. * attempts to negotiate for faster information transmission details.
  88. * At the moment, it asks for the right to use Ymodem (Wxmodem under
  89. * certain circumstances, but Wxmodem is not reliable), and then attempt
  90. * to use compaction on message transmission.
  91. *
  92. * The "both" parameter controls whether we go for both the protocol and
  93. * compaction options, or just the protocol.  This is used when we may be
  94. * only transferring files (where only protocol is useful) and Mass Transfers
  95. * are active.
  96. */
  97. void ITL_optimize(char both)
  98.   {
  99.   struct cmd_data cmds;
  100.   extern NetBuffer netBuf;
  101.   if (Optimized) return;
  102.   Optimized = TRUE;   /* ... or at least we tried */
  103.   #ifdef WXMODEM_AVAILABLE
  104.   zero_struct(cmds);
  105.   strCpy(cmds.fields[0], WXM_ITL);
  106.   cmds.command = ITL_PROTOCOL;
  107.   if (ItlWxmodem && sendNetCommand(&cmds, "ITL_opt"))
  108.     {
  109.     if( logNetResults && netDebug )splitF(netLog, "WXMODEM selected\n");
  110.     ITL_protocol = WXMDM;
  111.     ITLFunc = MsgOut = Table[ITL_protocol].method;
  112.  
  113.     }
  114.   else
  115.     {
  116.     if (ItlWxmodem && logNetResults && netDebug ) splitF(netLog, "No WXMODEM\n");
  117.     zero_struct(cmds);
  118.     strCpy(cmds.fields[0], YM_ITL);
  119.     cmds.command = ITL_PROTOCOL;
  120.     if (sendNetCommand(&cmds, "ITL_opt"))
  121.       {
  122.       if( logNetResults && netDebug )splitF(netLog, "YMODEM selected\n");
  123.       ITL_protocol = YMDM;
  124.       ITLFunc = MsgOut = Table[ITL_protocol].method;
  125.  
  126.       }
  127.     else if( logNetResults && netDebug )splitF(netLog, "No YMODEM\n");
  128.  
  129.     }
  130.   #else
  131.   zero_struct(cmds);
  132.   strCpy(cmds.fields[0], YM_ITL);
  133.   cmds.command = ITL_PROTOCOL;
  134.   if (sendNetCommand(&cmds, "ITL_opt"))
  135.     {
  136.     if( logNetResults && netDebug )splitF(netLog, "YMODEM selected\n");
  137.     ITL_protocol = YMDM;
  138.     ITLFunc = MsgOut = Table[ITL_protocol].method;
  139.  
  140.     }
  141.   else  if( logNetResults && netDebug )splitF(netLog, "No YMODEM\n");
  142.   #endif
  143.   zero_struct(cmds);
  144.   strCpy(cmds.fields[0], COMPACT_1);
  145.   cmds.command = ITL_COMPACT;
  146.   if (!both) return;
  147.   if (sendNetCommand(&cmds, "ITL compact"))
  148.     {
  149.     MsgOut = Encode;
  150.     MsgIn  = Decode;
  151.  
  152.     }
  153.   else
  154.     {
  155.     if( logNetResults && netDebug )splitF(netLog, "No compaction\n");
  156.     ITLFunc = MsgOut = Table[ITL_protocol].method;
  157.  
  158.     }
  159.  
  160.   }
  161. /*
  162. * ITL_Receive()
  163. *
  164. * This sets up the system to receive an ITL transmission.  Please note how
  165. * this function is blind to the actual content of what is coming in.
  166. *
  167. * Inputs:
  168. * o FileName - if NULL or zero length, this indicates the transmission should
  169. *   be to an internal buffer and shouldn't exceed 128 bytes.  If it is a valid
  170. *   filename (can be opened) then a file by that name should be created (not
  171. *   appended to) and the incoming stuff written to it.  In the former case the
  172. *   input should be placed directly into the buffer, while in the latter case
  173. *   the indirect function parameter WriteFn should be used.
  174. * o ReplyFirst - if TRUE, then send a positive reply to the facility request
  175. *   (whatever it is) before beginning reception.  A kludge to save space.
  176. * o OpenIt - if FALSE, then don't attempt to open the named file.  If TRUE,
  177. *   then open the named file using the global FILE descriptor upfd.
  178. * o WriteFn - Possibly NULL function to be used for file reception.
  179. * o CloseFn - The function to be called once reception is finished.
  180. *
  181. * Returns:
  182. * o ITL_SUCCESS - reception successful.
  183. * o ITL_BAD_TRANS - reception unsuccessful.
  184. * o ITL_NO_OPEN - reception unsuccessful.
  185. */
  186. char ITL_Receive(FileName, ReplyFirst, OpenIt, WriteFn, CloseFn)
  187. char *FileName;   /* If this is NULL or length = 0, then ITL data */
  188. /* should be placed in an internal buffer       */
  189. int ReplyFirst;  /* Should we do a reply(GOOD) call first?       */
  190. int OpenIt;    /* FIle needs opening?        */
  191. int (*WriteFn)(int c);  /* Writing the received data      */
  192. int (*CloseFn)(FILE *f);/* Closing out the file, if needed    */
  193.   {
  194.   extern char *WRITE_ANY;
  195.   extern FILE *upfd;
  196.   if (FileName == NULL || strLen(FileName) == 0)
  197.     {
  198.     if (ReplyFirst) reply(GOOD, "");
  199.     InternalCounter = 0;
  200.     /* This is temporary until we get WXMODEM available */
  201.     if (Reception(ITL_protocol, increment) == TRAN_SUCCESS)
  202.       {
  203.       return ITL_SUCCESS;
  204.  
  205.       }
  206.     else
  207.       {
  208.       killConnection();
  209.       return ITL_BAD_TRANS;
  210.  
  211.       }
  212.  
  213.     }
  214.   if (OpenIt)
  215.     {
  216.     if ((upfd = safeopen(FileName, WRITE_ANY)) == NULL)
  217.       {
  218.       /*    Handle an error at this point. */
  219.       if (ReplyFirst) reply(BAD, "System error");
  220.       sPrintf(ErrBuf, "ERROR: Couldn't open %s!", FileName);
  221.       netResult(ErrBuf);
  222.       return ITL_NO_OPEN;
  223.  
  224.       }
  225.     #ifdef HORRID_AMIGA_LATTICE_BUG
  226.     setnbf(upfd);
  227.     #endif
  228.  
  229.     }
  230.   if (ReplyFirst) reply(GOOD, "");
  231.   if (Reception(ITL_protocol, WriteFn) != TRAN_SUCCESS)
  232.     {
  233.     (*CloseFn)(upfd);
  234.     unlink(FileName);
  235.     killConnection();
  236.     return ITL_BAD_TRANS;
  237.  
  238.     }
  239.   else
  240.     {
  241.     (*CloseFn)(upfd);
  242.     return ITL_SUCCESS;
  243.  
  244.     }
  245.  
  246.   }
  247. /*
  248. * ITL_rec_optimize()
  249. *
  250. * This is called when the calling system wants to try to optimize the
  251. * information transfer protocol.  Supported protocols in this implementation
  252. * are Xmodem, Ymodem, and Wxmodem (iff WXMODEM_AVAILABLE is defined).
  253. */
  254. void ITL_rec_optimize(struct cmd_data *cmds)
  255.   {
  256.   int protocol;
  257.   #define WXMODEM_WORKS
  258.   #ifdef WXMODEM_WORKS
  259.   #ifdef WXMODEM_AVAILABLE
  260.   blah
  261.   protocol = atoi(cmds->fields[0]);
  262.   if (protocol < 0 || protocol > 2)
  263.   reply(BAD, "unrecognized protocol");
  264.   else
  265.     {
  266.     /* this is probably bad coding, really. */
  267.     reply(GOOD, "");
  268.     ITL_protocol = protocol + 1;    /* translates correctly for now */
  269.     ITLFunc = MsgOut = Table[ITL_protocol].method;
  270.     Optimized = TRUE;
  271.  
  272.     }
  273.   #else
  274.   protocol = atoi(cmds->fields[0]);
  275.   if (protocol < 0 || protocol > 2)
  276.   reply(BAD, "unrecognized protocol");
  277.   else
  278.     {
  279.     /* this is probably bad coding, really. */
  280.     if (strCmp(cmds->fields[0], WXM_ITL) == SAMESTRING)
  281.     reply(BAD, "can't trust");
  282.     else
  283.       {
  284.       reply(GOOD, "");
  285.       ITL_protocol = protocol + 1; /* translates correctly for now */
  286.       ITLFunc = MsgOut = Table[ITL_protocol].method;
  287.       Optimized = TRUE;
  288.  
  289.       }
  290.  
  291.     }
  292.   #endif
  293.   #else
  294.   protocol = atoi(cmds->fields[0]);
  295.   if (protocol < 0 || protocol > 2)
  296.   reply(BAD, "unrecognized protocol");
  297.   else
  298.     {
  299.     /* this is probably bad coding, really. */
  300.     if (strCmp(cmds->fields[0], WXM_ITL) == SAMESTRING)
  301.     reply(BAD, "can't trust");
  302.     else
  303.       {
  304.       reply(GOOD, "");
  305.       ITL_protocol = protocol + 1; /* translates correctly for now */
  306.       ITLFunc = MsgOut = Table[ITL_protocol].method;
  307.       Optimized = TRUE;
  308.  
  309.       }
  310.  
  311.     }
  312.   #endif
  313.  
  314.   }
  315. /*
  316. * ITL_RecCompact()
  317. *
  318. * This function receives the request to compact messages.  Only Compaction
  319. * method 0 (proprietary testing method) is currently supported.
  320. */
  321. void ITL_RecCompact(struct cmd_data *cmds)
  322.   {
  323.   if (atoi(cmds->fields[0]) == 0)
  324.     {
  325.     reply(GOOD, "");
  326.     MsgIn = Decode;
  327.     MsgOut = Encode;
  328.  
  329.     }
  330.   else reply(BAD, "unrecognized compaction");
  331.  
  332.   }
  333. /*
  334. * ITL_Send()
  335. *
  336. * This function is used to manage ITL transmissions.  It initializes the
  337. * sending protocol for the impending transmission, which includes signaling
  338. * the receiving system of the beginning of the protocol.  In event of failure,
  339. * it drops carrier and returns FALSE, otherwise it returns TRUE.
  340. *
  341. * NB: All users should check the return value of this function.
  342. */
  343. char ITL_Send(char mode)
  344.   {
  345.   int reason;
  346.   if ((reason = Transmission(ITL_protocol, mode)) != TRAN_SUCCESS)
  347.     {
  348.     if( logNetResults )
  349.       splitF(netLog, "\nITL_send failure %d, mode %d\n", reason, mode);
  350.     killConnection();
  351.     return FALSE;
  352.  
  353.     }
  354.   return TRUE;
  355.  
  356.   }
  357. /*
  358. * sendITLchar(c)
  359. *
  360. * This sends a single character (byte) via the ITL.
  361. */
  362. int sendITLchar(int c)
  363.   {
  364.   EncCount++;
  365.   return (*ITLFunc)(c);
  366.  
  367.   }
  368. /*
  369. * increment()
  370. *
  371. * This function is used to place incoming information into an internal buffer
  372. * for later processing.  It is used exclusively in calls to Reception.  See
  373. * ITL_Receive().
  374. */
  375. int increment(int c)
  376.   {
  377.   RecBuf[InternalCounter++] = c;
  378.   if (InternalCounter > SECTSIZE+2)
  379.     {
  380.     killConnection();
  381.     return FALSE;
  382.  
  383.     }
  384.   return TRUE;
  385.  
  386.   }
  387. /*
  388. * ITL_SendMessages()
  389. *
  390. * This function sets up to send messages to the receiver.  It returns
  391. * FALSE (and drops carrier) if it fails to get the transmission rolling.
  392. * On success, it intializes for compaction if appropriate and returns
  393. * TRUE.
  394. */
  395. char ITL_SendMessages()
  396.   {
  397.   EncCount = 0l;
  398.   if (!ITL_Send(STARTUP))
  399.   return FALSE;
  400.   ITLFunc = MsgOut;
  401.   if (MsgOut == Encode) StartEncode(Table[ITL_protocol].method);
  402.   return TRUE;
  403.  
  404.   }
  405. /*
  406. * ITL_StopMessages()
  407. *
  408. * This stops the transmission of messages to the receiver.
  409. */
  410. void ITL_StopSendMessages()
  411.   {
  412.   if (MsgOut == Encode)
  413.     {
  414.     StopEncode();
  415.  
  416.     }
  417.   if (gotCarrier())
  418.   ITL_Send(FINISH);
  419.   ITLFunc = Table[ITL_protocol].method;
  420.  
  421.   }
  422. /*
  423. * ITL_StartRecMsgs()
  424. *
  425. * This function receives messages from the other side.  Inputs:
  426. *
  427. * o FileNm - the filename to store the incoming messages in.
  428. * o ReplyFirst - should we reply positively first?  If not, don't reply at
  429. *   all.
  430. * o OpenIt - do we need to open the file first?
  431. * o OverRide - do we need to override the writing function?  If not, then
  432. *   this is NULL.
  433. */
  434. char ITL_StartRecMsgs(char *FileNm, char ReplyFirst, char OpenIt,
  435. int (*OverRide)(int c))
  436.   {
  437.   char toReturn;
  438.   int  CloseEncoded(FILE *f);
  439.   int  (*CloseFn)(FILE *f) = fclose;
  440.   if (OverRide == Encode) CloseFn = CloseEncoded;
  441.   if (MsgIn == Decode)
  442.     {
  443.     StartDecode((OverRide == NULL) ? putFLChar : OverRide);
  444.     OverRide = NULL;
  445.  
  446.     }
  447.   toReturn = ITL_Receive(FileNm, ReplyFirst, OpenIt,
  448.   (OverRide == NULL) ? MsgIn : OverRide, CloseFn);
  449.   if (MsgIn == Decode) StopDecode();
  450.   return toReturn;
  451.  
  452.   }
  453. /*
  454. * CloseEncoded()
  455. *
  456. * This stops encoding before closing a file, and is passed to ITL_Receive().
  457. * If this is NOT used, then the flushing of the compaction buffers will not
  458. * occur and data will be lost.
  459. */
  460. int CloseEncoded(FILE *f)
  461.   {
  462.   StopEncode();
  463.   return fclose(f);
  464.  
  465.   }
  466.